home *** CD-ROM | disk | FTP | other *** search
/ Amiga Plus 2000 #1 / Amiga Plus CD - 2000 - No. 1.iso / Tools / Dev / Meshwriter / lightwave.c < prev    next >
Encoding:
C/C++ Source or Header  |  1999-12-03  |  9.0 KB  |  331 lines

  1. /*
  2. **      $VER: lightwave.c 1.00 (27.03.1999)
  3. **
  4. **      Creation date : 01.01.1999
  5. **
  6. **      Description       :
  7. **         Standart saver module for meshwriter.library.
  8. **         Saves the mesh as Lightwave file.
  9. **
  10. **
  11. **      Written by Stephan Bielmann
  12. **
  13. */
  14.  
  15. /*************************** Includes *******************************/
  16.  
  17. /*
  18. ** Amiga includes
  19. */
  20. #include <dos/stdio.h>
  21.  
  22. #include <clib/dos_protos.h>
  23.  
  24. /*
  25. ** Project includes
  26. */
  27. #include "meshwriter_private.h"
  28. #include "utilities.h"
  29.  
  30. /**************************** Defines *******************************/
  31.  
  32. /*
  33. ** Number of elements in the buffers
  34. */
  35. #define Ci_BUFFERS  100    // constant buffer size
  36. #define Ci_MAXPOLYS 200    // maximum number of polygons
  37.  
  38. /*********************** Type definitions ***************************/
  39.  
  40. /*
  41. ** Private type definitions
  42. */
  43. typedef struct {
  44.     FLOAT x,y,z;
  45. } LWOBVertex;
  46.  
  47. typedef struct {
  48.     UBYTE name[4];
  49.     ULONG size;
  50. } LWOBChunk;
  51.  
  52. typedef struct {
  53.     UBYTE name[4];
  54.     UWORD size;
  55. } LWOBSubChunk;
  56.  
  57. typedef struct {
  58.     LWOBSubChunk chunk;
  59.     UBYTE r,g,b,n;
  60. } LWOBColrChunk;
  61.  
  62. typedef struct {
  63.     LWOBSubChunk chunk;
  64.     UWORD w;
  65. } LWOBWordChunk;
  66.  
  67. /********************** Private functions ***************************/
  68.  
  69. /********************** Public functions ****************************/
  70.  
  71. /********************************************************************\
  72. *                                                                    *
  73. * Name         : write3LWOB                                          *
  74. *                                                                    *
  75. * Description  : Writes a standart lightwave object binary file.     *
  76. *                Revision date : 28.11.1994                          *
  77. *                                                                    *
  78. * Arguments    : lwobfile  IN : An already opened file stream.       *
  79. *                mesh      IN : Pointer to the mesh.                 *
  80. *                                                                    *
  81. * Return Value : RCNOERROR                                           *
  82. *                RCWRITEDATA                                         *
  83. *                RCVERTEXINPOLYGONOVERFLOW                           *
  84. *                                                                    *
  85. * Comment      :                                                     *
  86. *                                                                    *
  87. \********************************************************************/
  88. ULONG write3LWOB(BPTR lwobfile, TOCLMesh *mesh) {
  89.     LWOBChunk            form,pnts,srfs,pols,surf;
  90.     LWOBColrChunk        colr;
  91.     LWOBWordChunk        glos,tran;
  92.     
  93.     TOCLVertexNode                *ver=NULL;
  94.     TOCLMaterialNode            *mat=NULL;    
  95.     TOCLPolygonNode            *pln=NULL;
  96.     TOCLPolygonsVerticesNode    *plvi=NULL;
  97.     
  98.     LWOBVertex            vbuffer[Ci_BUFFERS];    // Ci_BUFFERS  * sizeof(LWOBVertex)    vertices buffer
  99.     UWORD                pbuffer[Ci_MAXPOLYS];    // Ci_MAXPOLYS * sizeof(UWORD)        polygons buffer
  100.     ULONG                bufferstate;
  101.     LONG                polybufstate;
  102.     ULONG                len;
  103.  
  104. // nicht mehr als uword vertices wegen polygon index = uword !!
  105.  
  106.     /*
  107.     ** Initializing all chunks and theyr sizes and static contents
  108.     */    
  109.     setUBYTEArray(pnts.name,"PNTS",4);
  110.     pnts.size=mesh->vertices.numberOfVertices*sizeof(FLOAT)*3;
  111.     
  112.     setUBYTEArray(srfs.name,"SRFS",4);
  113.     // compute its size
  114.     srfs.size=0;
  115.     if(mesh->materials.firstNode) {
  116.         mat=mesh->materials.firstNode;
  117.         do {
  118.             srfs.size+=stringlen(mat->name);
  119.           
  120.               // check if odd or not
  121.             if(srfs.size) {
  122.                 if ((srfs.size+1)%2) {
  123.                     srfs.size+=2;
  124.                 } else {
  125.                     srfs.size++;
  126.                 }
  127.             }
  128.             
  129.             mat=mat->next;
  130.         } while(mat!=NULL);
  131.     }
  132.  
  133.     setUBYTEArray(surf.name,"SURF",4);
  134.  
  135.     setUBYTEArray(pols.name,"POLS",4);
  136.     // size = numberOfPolygons * 4 (for the polygon size and surface index)
  137.     // and number of vertex indices * 2
  138.     pols.size=0;
  139.       if(mesh->polygons.firstNode!=NULL) {                 
  140.         pln=mesh->polygons.firstNode;
  141.         do {
  142.             pols.size+=pln->numberOfVertices*2+4;
  143.             
  144.             pln=pln->next;
  145.         } while (pln!=NULL);
  146.     } 
  147.  
  148.     setUBYTEArray(colr.chunk.name,"COLR",4);
  149.     colr.chunk.size = 4;        // fixed size
  150.     colr.n = 0;                // fixed value
  151.  
  152.     setUBYTEArray(glos.chunk.name,"GLOS",4);
  153.     glos.chunk.size = 2;        // fixed size
  154.  
  155.     setUBYTEArray(tran.chunk.name,"TRAN",4);
  156.     tran.chunk.size = 2;        // fixed size
  157.  
  158.     setUBYTEArray(form.name,"FORM",4);
  159.     form.size=0;
  160.     // size += 8 for pnts chunk and its size, if existent    
  161.     if(mesh->vertices.firstNode!=NULL) {
  162.           form.size += 8 + pnts.size;
  163.       }
  164.     // size += 8 for srfs chunk and its size, if existent
  165.     // size += numberOfMaterials * 8 for surf chunk and its size. if existent
  166.     if(mesh->materials.firstNode!=NULL) {
  167.           form.size += 8 + srfs.size;
  168.           
  169.         // size of srfs and number of materials * (size and content of colr,glos,tran and 8 for surf itself)
  170.         form.size += srfs.size + mesh->materials.numberOfMaterials * (10+8+8+8);
  171.       }
  172.       // size += 8 for pols chunk and its size, if existent
  173.       if(mesh->polygons.firstNode!=NULL) {
  174.         form.size += 8 + pols.size;
  175.       }
  176.       // size += 4 for LWOB 
  177.       form.size += 4;
  178.     
  179.     /*
  180.     ** Writing the chunks and theyr dynamic content
  181.     */
  182.     if(FWrite(lwobfile,&form,sizeof(form),1)!=1) return(RCWRITEDATA);
  183.  
  184.     if(FWrite(lwobfile,"LWOB",1,4)!=4) return(RCWRITEDATA);
  185.         
  186.     // if there are vertices
  187.     if(mesh->vertices.firstNode!=NULL) {
  188.         if(FWrite(lwobfile,&pnts,sizeof(pnts),1)!=1) return(RCWRITEDATA);
  189.     
  190.         // initialize the buffer state
  191.         bufferstate=0;
  192.         
  193.         ver=mesh->vertices.firstNode;
  194.         do {
  195.             TOCLVertex v=ver->vertex;
  196.  
  197.             vbuffer[bufferstate].x=v.x;
  198.             vbuffer[bufferstate].y=v.z;
  199.             vbuffer[bufferstate].z=v.y;
  200.  
  201.             // check if the buffer is full and write and initialize it
  202.             if (++bufferstate==Ci_BUFFERS) {
  203.                 if(FWrite(lwobfile,&vbuffer,Ci_BUFFERS*sizeof(LWOBVertex),1)!=1) return(RCWRITEDATA);
  204.                 bufferstate=0;
  205.             }
  206.  
  207.             ver=ver->next;
  208.         } while(ver!=NULL);
  209.  
  210.         // write the rest of the buffer if there is any
  211.         if (bufferstate!=0) {
  212.             if(FWrite(lwobfile,&vbuffer,bufferstate*sizeof(LWOBVertex),1)!=1) return(RCWRITEDATA);
  213.             bufferstate=0;
  214.         }            
  215.     }
  216.  
  217.     // writing the material names in this object, if there are some
  218.     if(mesh->materials.firstNode) {
  219.         if(FWrite(lwobfile,&srfs,sizeof(srfs),1)!=1) return(RCWRITEDATA);
  220.  
  221.         mat=mesh->materials.firstNode;
  222.         do {
  223.             len=stringlen(mat->name);
  224.           
  225.             // write the name, add a '\0' and two of them if the size of the name + \0 is odd
  226.             if(len) {
  227.                 if(FWrite(lwobfile,mat->name,len,1)!=1) return(RCWRITEDATA);
  228.                 if ((len+1)%2) {
  229.                     if(FWrite(lwobfile,"\0\0",2,1)!=1) return(RCWRITEDATA);
  230.                 } else {
  231.                     if(FWrite(lwobfile,"\0",1,1)!=1) return(RCWRITEDATA);
  232.                 }
  233.             }
  234.             
  235.             mat=mat->next;
  236.         } while(mat!=NULL);
  237.     }
  238.  
  239.     // write the polygons with surface index, if there are any
  240.     // they have to be written clockwise ! and Ci_MAXPOLYS points each polygon "only"
  241.     if (mesh->polygons.firstNode!=NULL) {
  242.         UWORD w;
  243.         
  244.         if(FWrite(lwobfile,&pols,sizeof(pols),1)!=1) return(RCWRITEDATA);
  245.  
  246.         // initialize the buffer state
  247.         polybufstate=Ci_MAXPOLYS-1;
  248.         
  249.         pln=mesh->polygons.firstNode;
  250.         do {
  251.             plvi=pln->firstNode;
  252.             
  253.             do {    
  254.                 // transform from counterclockwise to clockwise
  255.                 pbuffer[polybufstate--]=plvi->vertexNode->index-1;
  256.                 
  257.                 // check if there are to much vertices in this polygon
  258.                 if (polybufstate<0) {
  259.                     return(RCVERTEXINPOLYGONOVERFLOW);
  260.                 }
  261.                 
  262.                 plvi=plvi->next;
  263.             } while(plvi!=NULL);                        
  264.  
  265.             // write the number of vertices in this polygon
  266.             w=pln->numberOfVertices;
  267.             if(FWrite(lwobfile,&w,sizeof(UWORD),1)!=1) return(RCWRITEDATA);                      
  268.  
  269.             // write down the buffer
  270.             if(FWrite(lwobfile,&pbuffer[polybufstate+1],w*sizeof(UWORD),1)!=1) return(RCWRITEDATA);                      
  271.             polybufstate=Ci_MAXPOLYS-1;
  272.  
  273.             // add the surface index
  274.             if (pln->materialNode) {
  275.                 w=pln->materialNode->index;
  276.             } else {
  277.                 // no material => index = 0
  278.                 w=0;
  279.             }
  280.             if(FWrite(lwobfile,&w,sizeof(UWORD),1)!=1) return(RCWRITEDATA);                      
  281.             
  282.             pln=pln->next;
  283.         } while (pln!=NULL);        
  284.     }
  285.  
  286.     // writing the materials if there are some
  287.     if(mesh->materials.firstNode) {
  288.  
  289.         mat=mesh->materials.firstNode;
  290.         do {
  291.             len=stringlen(mat->name);
  292.           
  293.             surf.size = len+1;
  294.             // if the size of the name + \0 is odd, we have to pad it => +1
  295.             if (surf.size%2) surf.size++;
  296.             surf.size += colr.chunk.size + glos.chunk.size + tran.chunk.size + 3 * 6;
  297.             
  298.             if(FWrite(lwobfile,&surf,sizeof(surf),1)!=1) return(RCWRITEDATA);
  299.  
  300.             // write its name, add a '\0' and two of them if the size of the name + \0 is odd
  301.             if(len) {
  302.                 if(FWrite(lwobfile,mat->name,len,1)!=1) return(RCWRITEDATA);
  303.                 if ((len+1)%2) {
  304.                     if(FWrite(lwobfile,"\0\0",2,1)!=1) return(RCWRITEDATA);
  305.                 } else {
  306.                     if(FWrite(lwobfile,"\0",1,1)!=1) return(RCWRITEDATA);
  307.                 }
  308.             }
  309.             
  310.             // diffuse color
  311.             colr.r=mat->diffuseColor.r, colr.g=mat->diffuseColor.g, colr.b=mat->diffuseColor.b;
  312.             if(FWrite(lwobfile,&colr,sizeof(colr),1)!=1) return(RCWRITEDATA);
  313.  
  314.             // glossiness
  315.             glos.w=(UWORD)(mat->shininess*256);
  316.             if(FWrite(lwobfile,&glos,sizeof(glos),1)!=1) return(RCWRITEDATA);
  317.  
  318.             // transparecy
  319.             tran.w=(UWORD)(mat->transparency*256);
  320.             if(FWrite(lwobfile,&tran,sizeof(tran),1)!=1) return(RCWRITEDATA);
  321.  
  322.             mat=mat->next;
  323.  
  324.         } while(mat!=NULL);
  325.     }
  326.  
  327.     return(RCNOERROR);
  328. }
  329.  
  330. /************************* End of file ******************************/
  331.